package com.tinyideatech.admin.controller.car;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.zxing.WriterException;
import com.tinyideatech.common.core.controller.BaseController;
import com.tinyideatech.common.core.entity.ApiResult;
import com.tinyideatech.common.core.entity.PageResult;
import com.tinyideatech.common.core.text.Convert;
import com.tinyideatech.common.utils.StringUtils;
import com.tinyideatech.framework.dto.FTP;
import com.tinyideatech.framework.utils.ExcelUtils;
import com.tinyideatech.framework.utils.FtpUtil;
import com.tinyideatech.system.entity.CarCode;
import com.tinyideatech.system.entity.CarDevice;
import com.tinyideatech.system.entity.CarRmonOrder;
import com.tinyideatech.system.service.ICarCodeService;
import com.tinyideatech.system.service.ICarDeviceService;
import com.tinyideatech.system.service.ICarGoodsService;
import com.tinyideatech.system.service.ICarRmonOrderService;
import com.tinyideatech.wechat.utils.CommonUtil;
import com.tinyideatech.wechat.utils.RandomUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author zhangy-5
 * @date 2019-12-15
 */

@ApiOperation("远程监控订单")
@Controller
@RequestMapping("/ws/v2/rmon")
public class CarRmonOrderController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(CarRmonOrderController.class);

    private WxPayService wxService;

    @Autowired
    private ICarRmonOrderService carRmonOrderService;

    @Autowired
    private ICarCodeService carCodeService;

    @Autowired
    private ICarGoodsService goodsService;

    @Autowired
    private ICarDeviceService carDeviceService;

    @Autowired
    private FTP ftpCatalog;

    @Autowired
    public CarRmonOrderController(WxPayService wxService) {
        this.wxService = wxService;
    }

    @Value("${wx.pay.notifyUrl.rmon}")
    private String notifyUrl;

    @Value("${wx.pay.tradeType}")
    private String tradeType;

    @GetMapping()
    public String list() {
        return "code/rmon/list";
    }

    @GetMapping("/add")
    public String add() {
        return "code/rmon/add";
    }

    @GetMapping("/edit/{id}")
    public String carRmonOrderEdit(
            @PathVariable("id") Long id,
            ModelMap map
    ) {
        CarRmonOrder carRmonOrder = carRmonOrderService.getById(id);
        map.addAttribute("carRmonOrder", carRmonOrder);
        return "system/order/edit";
    }

    @ResponseBody
    @PostMapping("/list")
    public PageResult list(CarRmonOrder carRmonOrder) {
        QueryWrapper<CarRmonOrder> qw = new QueryWrapper<>();
        if (StringUtils.isNotEmpty("")) {
            qw.like("", "");
        }
        IPage<CarRmonOrder> page = startPage();
        IPage<CarRmonOrder> carRmonOrderList = carRmonOrderService.page(page, qw);
        return page(carRmonOrderList);
    }

    @ResponseBody
    @PostMapping("/save")
    public ApiResult save(
            CarRmonOrder sysRole
    ) {
        carRmonOrderService.saveOrUpdate(sysRole);
        return success();
    }

    @ResponseBody
    @PostMapping("/remove")
    public ApiResult remove(
            String ids
    ) {
        Long[] carRmonOrderIds = Convert.toLongArray(ids);
        carRmonOrderService.removeByIds(Arrays.asList(carRmonOrderIds));
        return success();
    }

    @PostMapping("/verify/status")
    @ResponseBody
    public ApiResult changeStatus(@RequestParam String deviceId) {
        Integer result = carDeviceService.verifyRmon(deviceId);
        if (result.equals(0)) {
            return success("not active");
        }
        if (result.equals(1)) {
            return success("active");
        }
        return success("renew");
    }


    @ApiOperation(value = "RMON调试用发起订单")
    @PostMapping("/scanpay")
    @ResponseBody
    private ApiResult rmonOrder(@RequestParam String deviceId,
                                HttpServletRequest request) {
        try {
            JSONObject resultJSON = new JSONObject();
            JSONObject compare = carRmonOrderService.compareQRcodeTime(deviceId);
            if (compare.size() != 0) {
                return ApiResult.success("", compare);
            }
            WxPayUnifiedOrderRequest wxReq = new WxPayUnifiedOrderRequest();
            String outTradeNo = RandomUtil.getOrderIdByUUId();
            String expireTime = CommonUtil.getOrderExpireTime(15 * 60 * 1000L);
            String productId = RandomUtil.generateStr(10, deviceId, 1);
            wxReq.setBody("鑫洋泉远程激活业务");
            wxReq.setDetail("鑫洋泉远程激活-RMON");
            wxReq.setOutTradeNo(outTradeNo);
            wxReq.setTotalFee(goodsService.getPrice(4));
            wxReq.setSpbillCreateIp(carRmonOrderService.ip(request));
            wxReq.setTimeExpire(expireTime);
            wxReq.setProductId(productId);
            wxReq.setNotifyUrl(notifyUrl);
            wxReq.setTradeType(tradeType);
            WxPayUnifiedOrderResult result = this.wxService.unifiedOrder(wxReq);
            log.info(String.format("result:[%s]", result.toString()));
            boolean isSuccess = carRmonOrderService.verifyWxPayUnifiedOrderResult(result, deviceId, outTradeNo, expireTime);
            if (isSuccess) {
                log.info(String.format("Dmon-CodeURL:[%s]", result.getCodeURL()));
                BufferedImage image = CommonUtil.getQRCodeImge(result.getCodeURL());
                String fileName = "wx" + outTradeNo + ".png";
                FtpUtil.uploadFileToFtp(ftpCatalog.getFTPPathImgFtp(), fileName, FtpUtil.bufferedImageToInputStream(image));
                resultJSON.put("url", ftpCatalog.getFullPathImgFtp() + fileName);
                resultJSON.put("prepayId", result.getPrepayId());
                return ApiResult.success(resultJSON);
            }
        } catch (WxPayException e) {
            e.printStackTrace();
            log.error("unknow error:" + e.getMessage());
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return error();
    }

    /**
     * 扫码支付回调
     *
     * @param xmlData
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "RMON扫码支付回调通知处理")
    @PostMapping("/notify/scanpay")
    @ResponseBody
    public String parseScanPayNotifyResult(@RequestBody String xmlData) throws Exception {
        final WxPayOrderNotifyResult result = this.wxService.parseOrderNotifyResult(xmlData);
        if (carRmonOrderService.verifyNotifyResult(result, xmlData)) {
            return WxPayNotifyResponse.success("SUCCESS");
        } else {
            return WxPayNotifyResponse.fail("FAIL");
        }
    }


    @ApiOperation(value = "RMON扫码支付回调验证")
    @PostMapping("/verify/order")
    @ResponseBody
    public ApiResult verifyRMONOrder(@RequestParam String prepayId) {
        CarRmonOrder carRmonOrder = carRmonOrderService
                .getOne(new QueryWrapper<CarRmonOrder>()
                        .eq("prepay_id", prepayId));
        if (carRmonOrder == null) {
            return ApiResult.error("pay error");
        }
        JSONObject code = new JSONObject();
        List<CarCode> codes = carCodeService.list(new QueryWrapper<CarCode>()
                .eq("device_id", carRmonOrder.getDeviceId()));
        List<CarCode> availableCodes = carCodeService.list(new QueryWrapper<CarCode>()
                .eq("status", 0)
                .eq("type", 1));
        if (availableCodes.size() == 0) {
            return ApiResult.error("", "no codes available");
        }
        if (codes.size() != 0) {
            CarCode carCode = codes.get(0);
            code.put("p2pCode", carCode.getCode());
            code.put("nabtoId", carCode.getNabtoId());
            CarDevice car = carDeviceService.getOne(new QueryWrapper<CarDevice>()
                    .eq("device_id", carRmonOrder.getDeviceId()));
            if (car.getDmonEndTime().after(new Date())) {
                if (carRmonOrder.getPaymentResult().equals("1")) {
                    return ApiResult.success("renew success", code);
                } else {
                    return ApiResult.warn("pay fail");
                }
            } else {
                carCode.setDeviceId("");
                carCode.setStatus(0);
                carCodeService.updateById(carCode);
                if (carRmonOrder.getPaymentResult().equals("1")) {
                    CarCode available = availableCodes.get(0);
                    code.put("p2pCode", available.getCode());
                    code.put("nabtoId", available.getNabtoId());
                    return ApiResult.success("renew success", code);
                } else {
                    return ApiResult.warn("pay fail");
                }
            }
        } else {
            if (carRmonOrder.getPaymentResult().equals("1")) {
                CarCode update = availableCodes.get(0);
                update.setStatus(1);
                update.setDeviceId(carRmonOrder.getDeviceId());
                carCodeService.updateById(update);
                code.put("p2pCode", update.getCode());
                code.put("nabtoId", update.getNabtoId());
                return ApiResult.success("code", code);
            } else {
                return ApiResult.warn("pay fail");
            }
        }
    }


    /**
     * 验证设备远程监控过期时间
     *
     * @param deviceId
     * @return
     */
    @ApiOperation(value = "RMON验证过期时间")
    @PostMapping("/verify/expire")
    @ResponseBody
    public ApiResult verifyExpireTime(@RequestParam String deviceId) {
        List<CarDevice> d = carDeviceService.list(new QueryWrapper<CarDevice>()
                .eq("device_id", deviceId));
        JSONObject result = new JSONObject();
        if (d.size() == 0) {
            result.put("startTime", "");
            result.put("endTime", "");
            return success(result);
        }
        CarDevice device = d.get(0);
        if (device.getDeviceRmon() == null || device.getDeviceRmon() == 0) {
            return ApiResult.warn("302");
        }
        Date start = carRmonOrderService.startServiceTime(deviceId);
        result.put("startTime", start);
        result.put("endTime", device.getDmonEndTime());
        if (device.getDmonEndTime().after(new Date())) {
            return ApiResult.success(result);
        }
        return ApiResult.warn("");
    }


    /**
     * 车机注册
     *
     * @param deviceId
     * @return
     */
    @ApiOperation(value = "RMON车机注册")
    @PostMapping("/register")
    @ResponseBody
    public ApiResult register(@RequestParam String deviceId,
                              @RequestParam String mobile,
                              @RequestParam String password,
                              @RequestParam String code) throws Exception {
        JSONObject result = carRmonOrderService.registerProvider(deviceId, mobile, password, code);
        if (result.size() != 0) {
            return ApiResult.success();
        }
        return ApiResult.error();
    }

    /**
     * 车机重置密码
     *
     * @param deviceId
     * @return
     */
    @ApiOperation(value = "RMON重置登录密码")
    @PostMapping("/pwd/reset")
    @ResponseBody
    public ApiResult reset(@RequestParam String deviceId,
                           @RequestParam String mobile,
                           @RequestParam String password,
                           @RequestParam String code) throws Exception {
        JSONObject result = carRmonOrderService.resetPwdProvider(deviceId, mobile, password, code);
        if (result.size() != 0) {
            return ApiResult.success();
        }
        return ApiResult.error();
    }

    /**
     * 车机修改密码
     *
     * @param deviceId
     * @return
     */
    @ApiOperation(value = "RMON修改登陆密码")
    @PostMapping("/pwd/edit")
    @ResponseBody
    public ApiResult edit(@RequestParam String deviceId,
                          @RequestParam String mobile,
                          @RequestParam String password,
                          @RequestParam String code) throws Exception {
        JSONObject result = carRmonOrderService.editPwdProvider(deviceId, mobile, password, code);
        if (result.size() != 0) {
            return ApiResult.success();
        }
        return ApiResult.error();
    }


    /**
     * 车机修改密码
     *
     * @param deviceId
     * @return
     */
    @ApiOperation(value = "设备编号获取nabto激活码")
    @PostMapping("/nabto")
    @ResponseBody
    public ApiResult getNabto(@RequestParam String deviceId) {
        CarCode carCode = carCodeService.getOne(new QueryWrapper<CarCode>().eq("device_id", deviceId));
        JSONObject jsonObject = new JSONObject();
        if (carCode == null) {
            return error("device has no nabto code");
        }
        jsonObject.put("nabtoId", carCode.getNabtoId());
        jsonObject.put("nabtoCode", carCode.getCode());
        return ApiResult.success(jsonObject);
    }


    /**
     * Excel下载
     *
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "导出订单Excel")
    @GetMapping("/export/order")
    public void orderExcel(HttpServletResponse response) {
        XSSFWorkbook wb = carRmonOrderService.downloadRecorder();
        String fileName = "CarRmonOrder报表.xlsx";
        ExcelUtils.init(fileName, response, wb);
    }


    /**
     * test
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/test/redis")
    @ResponseBody
    public JSONObject test(@RequestParam String params) {
        JSONObject result = new JSONObject();
        if (carRmonOrderService.test(params)) {
            result.put("redis", "niubi");
            return result;
        } else {
            result.put("redis", "buniubi");
            return result;
        }
    }
}
